const multer = require('multer');
const path = require('path');
const fs = require('fs-extra');
const randomstring = require('randomstring');
const cacheUtil = require('../../cacheUtil');
const { eventHub } = require('../../models/event-hub');
const utility = require('../../models/utility');

const storage = multer.diskStorage({
  destination(req, file, cb) {
    cb(null, cacheUtil.getConfigPath('uploadDir'));
  },
  filename(req, file, cb) {
    if (!req.uploadDest) {
      req.uploadDest = randomstring.generate(16);
    }
    // 如果是单文件上传，把文件名替换为随机字符串(与之前逻辑保持一致)
    // 如果是文件夹上传，把根目录名替换为随机字符串
    // note!!!: 暂不支持多文件夹上传，或文件夹与单文件混传，会导致路径错乱
    const [, ...rest] = file.originalname.split('/');
    const uploadFilename = [req.uploadDest, ...rest].join('/');
    const fullname = path.join(cacheUtil.getConfigPath('uploadDir'), uploadFilename);
    fs.ensureDirSync(path.dirname(fullname));
    cb(null, uploadFilename);
  },
});

// 用于上传单个文件和单个文件夹
const uploadForSingleAndDir = multer({ storage, preservePath: true });

// 用于上传多个文件
const uploadForMultiple = multer({ dest: cacheUtil.getConfigPath('uploadDir'), preservePath: true });

function makeUpload(fieldName, funcName) {
  return (req, res, next) => {
    const chan = utility.getSessionId();
    const totalBytes = parseInt(req.headers['content-length'] || 0, 10);
    let acceptedBytes = 0;
    req.on('data', (buf) => {
      acceptedBytes += buf.length;
      const progress = acceptedBytes / totalBytes;
      if (chan) {
        eventHub.emit(chan, 'upload', progress);
      }
    });

    if (funcName === 'array') {
      const arrayUpload = uploadForMultiple.array(fieldName);
      return arrayUpload(req, res, next);
    }
    if (funcName === 'single') {
      const arrayUpload = uploadForSingleAndDir.array(fieldName);
      // 让single同时兼容单文件夹与单文件上传
      return arrayUpload(req, res, () => {
        if (!req.files || !req.files.length) {
          req.file = null;
          delete req.files;
          return next();
        }
        const [file] = req.files;
        const { destination, originalname, filename } = file;
        if (originalname.indexOf('/') > 0) {
          // 目录上传
          const [dirOrinaglename] = originalname.split('/');
          const [dirFilename] = filename.split('/');
          req.file = {
            isDir: true,
            fieldname: fieldName,
            path: path.join(destination, dirFilename),
            filename: dirFilename,
            originalname: dirOrinaglename,
            destination,
          };
          delete req.files;
        } else if (req.files.length > 1) {
          throw new Error('not support multiple files');
        } else {
          req.file = file;
          delete req.files;
        }
        return next();
      });
    }
    throw new Error('only support single or array');
    // // 实际上传文件
    // return upload[funcName](fieldName)(req, res, next);
  };
}

function single(fieldName) {
  return makeUpload(fieldName, 'single');
}

function array(fieldName) {
  return makeUpload(fieldName, 'array');
}

module.exports = {
  single,
  array,
};
